package com.topdt.jbpm.web.struts.action;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.Result;
import org.jbpm.api.ProcessDefinition;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

import com.thx.common.struts2.CurdAction;
import com.thx.common.util.AppContext;
import com.thx.common.web.ActionResult;
import com.thx.log.LogUtil;
import com.topdt.jbpm.model.Activity;
import com.topdt.jbpm.model.ActorDefinDetail;
import com.topdt.jbpm.model.Flow;
import com.topdt.jbpm.model.FlowDetail;
import com.topdt.jbpm.model.Work;
import com.topdt.jbpm.service.ActivityService;
import com.topdt.jbpm.service.ActorDefinDetailService;
import com.topdt.jbpm.service.FlowDetailService;
import com.topdt.jbpm.service.FlowService;
import com.topdt.jbpm.service.JbpmService;
import com.topdt.jbpm.service.ProcessResource;
import com.topdt.jbpm.service.WorkService;
import com.topdt.jbpm.utils.ModuleConstant;

/**  
 *  @Project       : thx-workflow
 *  @Program Name  : com.topdt.jbpm.web.struts.action.FlowAction.java
 *  @Class Name    : FlowAction
 *  @Description   : 流程管理/流程列表
 *  @Author        : calonlan
 *  @Creation Date : 2015年1月30日 下午4:41:14 
 *  @ModificationHistory  
 *  Who        When          What 
 *  --------   ----------    -----------------------------------
 *  username   2015年1月30日       TODO
 */

@Namespace("/workflow")
@Action(value = "flow",
		results = {
		@Result(name = "list", location = "/workflow/flow/list.jsp"),
		@Result(name = "copy", location = "/workflow/flow/copy.jsp"),
		@Result(name = "json", type = "json", params = { "root", "result" })
		}
)
@Controller
@Scope("prototype")
public class FlowAction extends CurdAction<Flow> {

	@Autowired
	private FlowService flowService;
	@Autowired
	private FlowDetailService flowDetailService;
	@Autowired
	private ActivityService activityService;
	@Autowired
	private ActorDefinDetailService actorDefinDetailService;
	@Autowired
	private WorkService workService;
	@Autowired
	private JbpmService jbpmService;
	
	protected String detailId;
	
	@Override
	public void doDelete() {
		logger.debug("<进入>:doDelete方法   删除流程");
		if (StringUtils.isNotBlank(id)) {
			Flow flow = flowService.get(id);
			//如果流程还是草稿状态，说明没有使用，可以删除
			if (StringUtils.isBlank(flow.getJbpmFlowKey())) {
				List<FlowDetail> flowDetails = flowDetailService.findByFlowId(id);
				if (flow != null && flowDetails != null ) {
					jbpmService.delWorkStream(flowDetails, id);
					flowService.delete(id);
					setResult(ActionResult.SUCCESS, "成功删除流程！");
					LogUtil.log(ModuleConstant.FLOW, LogUtil.ACTION_DELETE, LogUtil.RESULT_SUCCESS, "删除流程");
				}
			//如果是发布状态，判断该流程是否被使用
			} else {
				List<Work> works = workService.findByJbpmFlowKey(flow.getJbpmFlowKey());
				//判断该流程是否已经被使用
				//已经使用
				if (works != null && works.size() > 0) {
					setResult(ActionResult.FAIL, "不可以删除，该流程已经被使用！");
				} else {
					List<FlowDetail> flowDetails = flowDetailService.findByFlowId(id);
					if (flow != null && flowDetails != null ) {
						jbpmService.delWorkStream(flowDetails, id);
						flowService.delete(id);
						setResult(ActionResult.SUCCESS, "成功删除流程！");
						LogUtil.log(ModuleConstant.FLOW, LogUtil.ACTION_DELETE, LogUtil.RESULT_SUCCESS, "删除流程");
					}
				}
			}
			
		} else {
			setResult(ActionResult.FAIL, "服务器异常！");
		}
	}

	@Override
	protected void doList() throws Exception {
		logger.debug("<进入>:doList方法   获取流程列表");
		list = flowService.getAllByFlowName(entity.getFlowName());
		int index = 1;
		for (Flow temp : list) {
			temp.setIndex(index);
			temp.setGridClass("treegrid-" + index);
			index += 1;
			List<FlowDetail> flowDetails = flowDetailService.findByFlowId(temp.getFlowId());
			for (FlowDetail detail : flowDetails) {
				detail.setIndex(index);
				detail.setGridClass("treegrid-"+index+" treegrid-parent-"+temp.getIndex());
				index += 1;
			}
			temp.setFlowDetails(flowDetails);
		} 
	}
	
	/** 
	 *  @Description    : 删除详细流程
	 *  @Method_Name    : delDetailFlow
	 *  @return 
	 *  @return         : String
	 *  @Creation Date  : 2015年1月30日 下午4:41:20 
	 *  @version        : v1.00
	 *  @Author         : calonlan
	 
	 *  @Update Date    : 2015年1月30日 下午4:41:20 
	 *  @Update Author  : calonlan
	 */
	public String delDetailFlow() {
		logger.debug("<进入>:delDetailFlow方法    删除详细流程");
		if (StringUtils.isNotBlank(detailId)) {
			FlowDetail flowDetail = flowDetailService.get(detailId);
			//如果流程还是草稿状态，说明没有使用，可以删除
			if (StringUtils.isBlank(flowDetail.getJbpmFlowKey())) {
				if (flowDetail != null) {
					if ("1".equals(flowDetail.getState())) {
						List<FlowDetail> flowDetails = new ArrayList<FlowDetail>();
						flowDetails.add(flowDetail);
						jbpmService.delWorkStream(flowDetails, flowDetail.getFlowId());
						setResult(ActionResult.SUCCESS, "已发布未使用的流程删除成功！");
					} else if ("0".equals(flowDetail.getState())) {
						jbpmService.delFlowDetail(flowDetail);
						setResult(ActionResult.SUCCESS, "未发布的流程删除成功！");
					}
					LogUtil.log(ModuleConstant.FLOW, LogUtil.ACTION_DELETE, LogUtil.RESULT_SUCCESS, "删除详细流程");
					//如果该流程下面的子流程没有了，则删除该流程
					List<FlowDetail> flowDetails = flowDetailService.findByFlowId(flowDetail.getFlowId());
					if (flowDetails == null || flowDetails.size() <= 0) {
						flowService.delete(flowDetail.getFlowId());
					}				}
			} else {
				//判断该流程是否已经被使用
				List<Work> works = workService.findByJbpmFlowIdAndKey(
						flowDetail.getJbpmFlowId(), flowDetail.getJbpmFlowKey());
				if (works != null && works.size() > 0) {
					setResult(ActionResult.FAIL, "不可以删除，该流程已经被使用！");
				} else {
					if (flowDetail != null) {
						if ("1".equals(flowDetail.getState())) {
							List<FlowDetail> flowDetails = new ArrayList<FlowDetail>();
							flowDetails.add(flowDetail);
							jbpmService.delWorkStream(flowDetails, flowDetail.getFlowId());
							setResult(ActionResult.SUCCESS, "已发布未使用的流程删除成功！");
						} else if ("0".equals(flowDetail.getState())) {
							jbpmService.delFlowDetail(flowDetail);
							setResult(ActionResult.SUCCESS, "未发布的流程删除成功！");
						}
						LogUtil.log(ModuleConstant.FLOW, LogUtil.ACTION_DELETE, LogUtil.RESULT_SUCCESS, "删除详细流程");
						//如果该流程下面的子流程没有了，则删除该流程
						List<FlowDetail> flowDetails = flowDetailService.findByFlowId(flowDetail.getFlowId());
						if (flowDetails == null || flowDetails.size() <= 0) {
							flowService.delete(flowDetail.getFlowId());
						}
					}
				}	
			}
			
		} else {
			setResult(ActionResult.FAIL, "服务器异常！");
		}
		return JSON;
	}
	
	
	@Override
	protected void doInput() throws Exception {
		logger.debug("<进入>:doInput方法");
		super.doInput();
	}

	@Override
	protected void doView() throws Exception {
		logger.debug("<进入>:doView方法");
		super.doView();
	}

	@Override
	protected void doSave() throws Exception {
		logger.debug("<进入>:doSave方法");
		super.doSave();
	}

	public String getDetailId() {
		return detailId;
	}

	public void setDetailId(String detailId) {
		this.detailId = detailId;
	}
	
	
	/** 
	 *  @Description    : 检查流程名称唯一性
	 *  @Method_Name    : checkFlowName 
	 *  @return         : void
	 *  @Creation Date  : 2015年3月23日 下午3:35:01 
	 *  @version        : v1.00
	 *  @Author         : calonlan
	 
	 *  @Update Date    : 2015年3月23日 下午3:35:01 
	 *  @Update Author  : calonlan
	 */
	public void checkFlowName() {
		logger.debug("<进入>:checkFlowName方法    检查流程名称唯一性");
		List<Flow> list = flowService.findByName(entity.getFlowName());
		try {
			if (list == null || list.size() <= 0) {
				writeJson("true");
			} else {
				if (list.get(0).getFlowId().equals(id)) {
					writeJson("true");
				}else if(StringUtils.isNotBlank(detailId)){
					FlowDetail detail = jbpmService.findFlowDetailByDetailId(detailId);
					if(detail!=null){
						if(detail.getFlowId().equals(list.get(0).getFlowId())){
							writeJson("true");
						}else{
							writeJson("false");
						}
					}
				}else {
					writeJson("false");
				}
			}
		} catch (IOException e) {
			logger.error("<错误>:检查流程名称唯一性失败",e);
			setResult(ActionResult.FAIL, "服务器异常！");
		}
	}
	
	
	/** 
	 *  @Description    : 复制流程
	 *  @Method_Name    : copyFlow 
	 *  @return         : void
	 *  @Creation Date  : 2015年3月23日 下午5:32:35 
	 *  @version        : v1.00
	 *  @Author         : calonlan
	 
	 *  @Update Date    : 2015年3月23日 下午5:32:35 
	 *  @Update Author  : calonlan
	 */
	public String copyFlow() {
		logger.debug("<进入>:copyFlow方法    复制流程");
		FlowDetail flowDetail = flowDetailService.get(detailId);
		Flow flow = flowService.get(flowDetail.getFlowId());
		
		Flow newFlow = new Flow();
		
		newFlow.setFlowName(entity.getFlowName());
		newFlow.setCreatTime(new Date());
		newFlow.setCompanyId(AppContext.getCurrentComId());
		newFlow.setIsInherent(flow.getIsInherent());
		flowService.save(newFlow);
		
		FlowDetail newFlowDetail = new FlowDetail();
		newFlowDetail.setFlowId(newFlow.getFlowId());
		newFlowDetail.setCreateTime(new Date());
		newFlowDetail.setState("0");
		newFlowDetail.setVersion("1");
		//替换流程名称
		try {
			String jsonStr = flowDetail.getJsonStr();
			jsonStr = jsonStr.replace(flow.getFlowName(), entity.getFlowName());
			newFlowDetail.setJson(jsonStr.getBytes("utf-8"));
			
			String xmlStr = flowDetail.getXmlStr();
			xmlStr = xmlStr.replace(flow.getFlowName(), entity.getFlowName());
			newFlowDetail.setXml(xmlStr.getBytes("utf-8"));
			
		} catch (Exception e) {
			logger.error("<错误>:复制流程失败",e);
			setResult(ActionResult.FAIL, "复制失败了！");
		}
		
		newFlowDetail.setCompanyId(AppContext.getCurrentComId());
		flowDetailService.save(newFlowDetail);
		
		List<Activity> activities = activityService.findByFlowDetailId(detailId);
		if (activities != null && activities.size() > 0) {
			Activity activity = null ;
			for (Activity temp : activities) {
				activity = new Activity();
				activity.setActivityName(temp.getActivityName());
				activity.setActorNUM(temp.getActorNUM());
				activity.setDoRule(temp.getDoRule());
				activity.setAssignerActivity(temp.getAssignerActivity());
				activity.setAssignmentParamKey(temp.getAssignmentParamKey());
				activity.setActorModel(temp.getActorModel());
				activity.setSeqNUM(temp.getSeqNUM());
				activity.setCompanyId(AppContext.getCurrentComId());
				activity.setFlowDetailId(newFlowDetail.getDetailId());
				activityService.save(activity);
				
				List<ActorDefinDetail> actorDefinDetails = 
						actorDefinDetailService.findByActivityId(temp.getActivityId());
				if (actorDefinDetails != null && actorDefinDetails.size() > 0) {
					ActorDefinDetail aDetail = null;
					for (ActorDefinDetail tem : actorDefinDetails) {
						aDetail = new ActorDefinDetail();
						aDetail.setActorType(tem.getActorType());
						aDetail.setActors(tem.getActors());
						aDetail.setActivityId(activity.getActivityId());
						aDetail.setCompanyId(AppContext.getCurrentComId());
						actorDefinDetailService.save(aDetail);
					}
				}
			}
		}
		
		setResult(ActionResult.SUCCESS, "复制成功");
		return JSON;
	}
	/**
	 * 
	 * @Description:<br>
	 * @return
	 */
	public String  toCopy(){
		logger.debug("<进入>:toCopy方法    跳转到copy页面");
		logger.info("<提示>:"+detailId);
		return "copy";
	}
	
	/**
	 * 发布
	 * @param request
	 * @param response
	 */
	public String release(){
		logger.debug("<进入>:release方法    发布流程");
		try {
			FlowDetail flowDetail = jbpmService.findFlowDetailByDetailId(detailId);
			// 获取对应的xml流程文件,并获取到jbpm_flow_id,jbpm_flow_key
			Flow flow = jbpmService.getFlowByFlowId(flowDetail.getFlowId());
			ByteArrayInputStream xml = new ByteArrayInputStream(flowDetail.getXml());
			ProcessResource resource = new ProcessResource();
		    resource.setInputStream(xml);//xml 流
			resource.setName(flow.getFlowName()+".jpdl.xml");
			ProcessResource imgResource = jbpmService.getProcessImag(resource);//图片
			xml.reset();
			ProcessDefinition defin = jbpmService.deploy(resource,imgResource);
			String jbpmFlowId = "";
			String jbpmFlowKey = "";
			if(defin!=null && !"".equals(defin)){
				jbpmFlowId = defin.getId();
				jbpmFlowKey = defin.getKey();
			}
			//更新数据库
			jbpmService.update(jbpmFlowId,jbpmFlowKey,flow,flowDetail);
			LogUtil.log(ModuleConstant.DEFINE_FLOW, LogUtil.ACTION_UPDATE, LogUtil.RESULT_SUCCESS, "发布流程");
			setResult(ActionResult.SUCCESS, "发布成功！");
		} catch (Exception e) {
			setResult(ActionResult.SUCCESS, "发布失败！");
			logger.error("<错误>:发布流程失败",e);
		}
		
		return JSON;
	}
	
}
